package com.llamarun;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.util.ArrayList;
import java.util.Random;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.Log;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
 
public class GameView extends SurfaceView implements SurfaceHolder.Callback 
{
	private static final String TAG = GameView.class.getSimpleName();
 
	private MainThread thread;
	private boolean threadIsRunning = false;
    private static boolean speedingUp = true;
	private boolean gameOver = false;
	private boolean isMovingUp = false;
	private boolean isMovingDown = true;
    public static int score = 0;
	private Llama llama;
    private int time = 0;
    
    //used to delay how fast you can shoot projectibles
    //trying to fix a race condition bug with this...
    private int shootTimer = 0;
    private boolean waitOnFire = false;
    
    public static int gameTime = 0;
    private int gameSpeed = 3;
    // right to left scroll tracker for near and far BG
    private GameObjectFactory objectFactory;
    private ArrayList<GameObject> gameObjects;
    
	Bitmap bMap = (Bitmap) BitmapFactory.decodeResource(getResources(), R.drawable.background);	
	Bitmap pauseBtn = (Bitmap) BitmapFactory.decodeResource(getResources(), R.drawable.pause);	
	private int screenWidth;
	private int screenHeight;
    Rect lead;
    Rect follow;
    Context myContext;
    
	public GameView(Context context) 
	{
		super(context);
		getHolder().addCallback(this);
		this.myContext = context;
		gameObjects = new ArrayList<GameObject>();
		llama = new Llama(this);
		gameObjects.add(llama);
		objectFactory = new GameObjectFactory(this);
		
	  	// create the game loop thread
		thread = new MainThread(getHolder(), this);
		// initialize the random number generator
		
		setFocusable(true);
	}
	
	public void pauseGame()
	{
		thread.onPause();
	}
	
	public void resumeGame()
	{
		thread.onResume();
		//thread.run();
	}
 
	public void addGameObject(GameObject object) {
		this.gameObjects.add(object);
	}
	
	@Override
	public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) 
	{
		
	}
 
	@Override
	public void surfaceCreated(SurfaceHolder holder) 
	{
		start();
		
		screenWidth = this.getWidth();
		screenHeight = this.getHeight();
		lead   = new Rect(0, 0, screenWidth, screenHeight);
		follow = new Rect(screenWidth, 0, 2*screenWidth, screenHeight);
	}
	
	public void start()
	{
		if(!threadIsRunning)
		{
			thread.start();
			System.out.println("thread wasn't running");
			threadIsRunning = true;
		}
		else
		{
			System.out.println("thread was running");
			thread.onResume();
		}
	}
 
	@Override
	public void surfaceDestroyed(SurfaceHolder holder) 
	{
		thread.onPause();
	}
 
	public void gameOver()
	{
		gameOver = true;
	}
	
	@Override
	public boolean onTouchEvent(MotionEvent event) 
	{
		if (shootTimer == 2){
			waitOnFire = false;
		}
		
		//if they click shoot 
		if(event.getX(0)<this.getWidth()/2 && !waitOnFire) {
			llama.shootProjectible();
			shootTimer = 0;
			waitOnFire = true;
			return super.onTouchEvent(event);
		}
		//if they click shoot but timer isn't up
		else if (event.getX(0)<getWidth()/2){
			return super.onTouchEvent(event);
		}
		//if they click the pause button...
		else if (event.getX(0)>this.screenWidth-BitmapFactory.decodeResource(getResources(), R.drawable.pause).getWidth() &&
				 event.getY(0)<BitmapFactory.decodeResource(getResources(), R.drawable.pause).getHeight()) {
			return super.onTouchEvent(event);
		}
		//else start rising...
		else {
		  if (event.getAction() == MotionEvent.ACTION_DOWN) {
			   isMovingUp = true;
			   isMovingDown = false;
			   Log.i(TAG, event.getAction()+"");
			   time = 0;

		  }
		  else if (event.getAction() == MotionEvent.ACTION_UP) {
			  isMovingUp = false;
			  isMovingDown= true;
		      Log.i(TAG, event.getAction()+"");
			  time = 0;

		  }
		  //thought this would work..sadly no
		  /*boolean test = super.onTouchEvent(event);
		  if (!test) {
			  return test;
		  }
		  return true;*/
		  shootTimer++;
		  return true;
		}
	}
	
	public void update()
	{
		if(speedingUp) {
		  gameTime++;
		}
		time++;
		Log.i(TAG, "time " +gameTime + "score " + score);
		// move the bitmaps by gamespeed pixels
		lead.left    -= gameSpeed;
		lead.right   -= gameSpeed;
		follow.left  -= gameSpeed;
		follow.right -= gameSpeed;
				
		if(lead.right <= 0)
		{

			lead.left    = 0;
			lead.right   = screenWidth;
			follow.left  = screenWidth;
			follow.right = 2*screenWidth;
		}
		
		if(isMovingDown)
		{
			llama.moveDown(time);
		}
		if(isMovingUp)
		{
			llama.moveUp(time);
		}
		//ask for a new gameobject from the factory
        GameObject newObject = objectFactory.createGameObject();
        
        //if factory decides to give us a new object then we add it
        if (newObject != null)
        {
    		Random generator = new Random();
    		newObject.setX(this.getWidth());
    		newObject.setY(generator.nextInt(this.getHeight()));
        	gameObjects.add(newObject);
        }
        
        
        //update objects and remove ones that are now off screen
        for (int i =0; i<gameObjects.size(); i++)
        {  	
			//really dumb way of doing collision detection of 
			//projectiles & enemies... but whatevs...
			GameObject temp = gameObjects.get(i).collideWithEnemy(gameObjects);
			if (temp!= null)
			{
				gameObjects.remove(temp);
				i--;
				score+=100;
			}
        	    	
        	
        	if (!gameObjects.get(i).equals(llama) && llama.collision(gameObjects.get(i)))
        	{
        		gameObjects.get(i).collideWithLlama(llama);
        	}
        	
        	// Remove the object if it is off screen and draw it otherwise.
        	if (gameObjects.get(i).offScreen(this))
        	{
        		gameObjects.remove(i);
        		i--;
        	}
        	else
        	{
            	gameObjects.get(i).update(gameTime);
            	//gameObjects.get(i).draw(canvas);
        	}
        }
        
		score++;
	}
	
	public void render(Canvas canvas)
	{		
		// draw the background
		canvas.drawBitmap(bMap, null, lead, null);
		canvas.drawBitmap(bMap, null, follow, null);	
		
	    //draw objects
        for (int i =0; i<gameObjects.size(); i++)
        {  	
          gameObjects.get(i).draw(canvas);
        }
		
		// draw the pause button
		canvas.drawBitmap(pauseBtn, screenWidth-65, 2, null);
		
		
        
        // Draw the current score.
        String scoreString = "Score: " + Integer.toString(score);
        Paint paint = new Paint();
        paint.setTextSize(24);
        paint.setColor(Color.parseColor("#894F37"));
        canvas.drawText(scoreString, 70, 25, paint);
        
        // End game check
 		if(gameOver == true)
 		{
 			if(readHighScore()<score)
 			{
 				saveHighScore();
 			}
 			Bitmap endSprite = BitmapFactory.decodeResource(getResources(), R.drawable.gameover);
 			canvas.drawBitmap(endSprite, (screenWidth/2 - endSprite.getWidth()/2), (screenHeight/2 - endSprite.getHeight()/2), null);
 			thread.onPause();
 		}
        
	}
	
	public void saveHighScore()
	{
		File file=new File(myContext.getFilesDir(), "highScore.dat");

	    try {
	      FileOutputStream fint = new FileOutputStream(file);
	      ObjectOutputStream ois = new ObjectOutputStream(fint);
	      ois.writeObject(score);
	      ois.close();

	    }
	    catch (Exception e) 
	    { 
	    	  e.printStackTrace(); 
	    }

	}
	
	   private int readHighScore()
	    {
	    	File file=new File(myContext.getFilesDir(), "highScore.dat");
	        try {

	          FileInputStream fint = new FileInputStream(file);
	          ObjectInputStream ois = new ObjectInputStream(fint);
	          int score=(Integer) ois.readObject();
	          ois.close();
	          return score;
	        }
	        catch (Exception e) { 
	        	e.printStackTrace(); 
	         }
			return 0;
	    }
	
	   public static void startSpeedingUp(){
		   speedingUp = true;
	   }
	   
	   public static void stopSpeedingUp(){
		   speedingUp = false;
	   }


	
}
